using System;
using System.Collections;
using System.Collections.Generic;
using System.Html;
using Nsb.Classes;
using WhirliGig.Classes;
using WhirliGigEdit.Classes;
using jQueryApi;

namespace ThisILove
{
    public static class ListEditor
    {
        public static string[] TextBoxOuterStyles = new string[]
                                                {
                                                    "display",
                                                    "position",
                                                    "color", "background-color",
                                                    "margin-top", "margin-left", "margin-right", "margin-bottom",
                                                    "padding-top", "padding-left", "padding-right", "padding-bottom",
                                                    "border-top-style", "border-left-style", "border-right-style", "border-bottom-style",
                                                    "border-top-color", "border-left-color", "border-right-color", "border-bottom-color",
                                                    "border-top-width", "border-left-width", "border-right-width", "border-bottom-width",
                                                    "border-top-left-radius", "border-top-right-radius", "border-bottom-left-radius", "border-bottom-right-radius",
                                                    "-webkit-border-radius","-webkit-border-top-radius", "-webkit-border-left-radius", "-webkit-border-right-radius", "-webkit-border-bottom-radius",
                                                    "-moz-border-radius","-moz-border-top-radius", "-moz-border-left-radius", "-moz-border-right-radius", "-moz-border-bottom-radius",
                                                    "font-family", "font-size", "font-weight", "text-decoration", "line-height", "white-space"
                                                };

        public static string[] TextBoxInnerStyles = new string[]
                                                {
                                                    "color", "background-color",
                                                    "font-family", "font-size", "font-weight", "text-decoration", "line-height"
                                                };

        public static Dictionary GetCssOuter(jQueryObject el)
        {
            Inform.Dump(el.Plugin<Jewl>().GetStyles(), "Styles");
            Dictionary css = new Dictionary();
            foreach (string s in TextBoxOuterStyles)
            {
                string v = el.GetCSS(s);
                if (!String.IsNullOrEmpty(v))
                    css[s] = v;
            }
            jQueryPosition p = el.GetOffset();
            css = (Dictionary) jQuery.Extend(css,
                                new Dictionary(
                                    "top", p.Top,
                                    "left", p.Left,
                                    "width", el.GetWidth(),
                                    "overflow", "visible",
                                    "white-space", "normal",
                                    "background-color", Css.RealBgColor(el)
                                    ));
            Inform.Dump(css, "OuterCss");
            return css;
        }

        public static Dictionary GetCssInner(jQueryObject el)
        {
            jQueryObject ctt = el.Children().First().Find(".GigC").First();
            Dictionary css = new Dictionary();
            foreach (string s in TextBoxInnerStyles)
            {
                css[s] = el.GetCSS(s);
            }
            jQueryPosition p = ctt.Position();
            css = (Dictionary)jQuery.Extend(css,
                                new Dictionary(
                                    "position", "relative", "top", -2, "left", -4,
                                    "width", ctt.GetInnerWidth(), "height", ctt.GetInnerHeight(),
                                    "overflow", "visible",
                                    "background-color", Css.RealBgColor(el),
                                    "border", "none",
                                    "margin", 0,
                                    "padding", "2px 4px"
                                    ));
            //jQuery.Extend(css, new Dictionary("top", p.Top - 1, "left", p.Left - 2, "width", ctt.GetInnerWidth() + 4, "height", ctt.GetInnerHeight() + 2));
            //jQuery.Extend(css, new Dictionary("padding-left", 2, "padding-right", 2, "padding-top", 1, "padding-bottom", 1));
            Inform.Dump(css, "InnerCss");
            return css;
        }

        public static string Value(jQueryObject el)
        {
            jQueryObject tx = (jQueryObject)el.GetDataValue("tx");
            if (tx != null)
                return tx.Plugin<Jewl>().GetValue();
            return null;
        }

        public static string EditFinish(jQueryObject el)
        {
            Cluster.GlassStay(false);
            Cluster.GlassOff(true);
            return Value(el);
        }

        public static void EditText(jQueryObject el, string content)
        {
            content = String.Format("{0}\n\t", content);
            bool isList = true;
            string wrap = isList ? "off" : "soft";
            jQueryObject bx = jQuery.FromHtml("<div/>");
            jQueryObject tx = jQuery.FromHtml("<textarea class='AboveHider' wrap='" + wrap + "' style='position:absolute;padding:0;margin:0;border: 0px none transparent'/>");
            el.Data("tx", tx);

            Dictionary<string, KeyAction> editKeys = new Dictionary(
                "13:s",
                (KeyAction)delegate(jQueryEvent ek)
                {
                    DomElement.CancelEvent(ek);
                    Cluster.GlassOff();
                },
                "27:", /*esc*/
                (KeyAction)delegate(jQueryEvent ek)
                {
                    DomElement.CancelEvent(ek);
                    //escape = true;
                    Cluster.GlassOff();
                },
                "9:", /*tab*/
                (KeyAction)delegate(jQueryEvent ek)
                {
                    DomElement.CancelEvent(ek);
                    Helpers.InsertText(tx, "\t");
                }
                );

            //Dictionary css = new Dictionary(
            //    "position", "absolute",
            //    "top", el.GetOffset().Top,
            //    "left", el.GetOffset().Left,
            //    "width", el.GetOuterWidth(),
            //    "height", el.GetOuterHeight()
            //    );

            Dictionary cssOuter = GetCssOuter(el);
            Dictionary cssInner = GetCssInner(el);

            bx
                .Append(tx)
                .AppendTo(Document.Body)
                .CSS(cssOuter)
                ;


            tx
                .CSS(cssInner)
                //.CSS(new Dictionary("border-style", "none"))
                .Plugin<Jewl>().FValue(content)
                .Bind("keydown.editev",
                      delegate(jQueryEvent e2)
                      {
                          string k = Keys.DoKeys(e2, editKeys);
                          if (k == null)
                              return;

                          if (isList)
                          {
                              if (e2.Which == 13)
                              {
                                  Window.SetTimeout(delegate { tx.Value(tx.GetValue().ReplaceRegex((RegularExpression)Script.Literal(@"/[\n]([^\t])|\n$/g"), "\n\t$1")); }, 1);
                              }
                              else if (e2.Which == 8)
                              {
                                  Window.SetTimeout(delegate { tx.Value(tx.GetValue().ReplaceRegex((RegularExpression)Script.Literal(@"/[\n]([^\t])|\n$/g"), "$1")); }, 1);
                              }
                          }
                      })
                .Click().Focus().Plugin<Jewl>().CarotToEnd()
                ;

            Cluster.Glass(delegate
            {
                Cluster.GlassStay();
                tx.Click().Focus().Plugin<Jewl>().CarotToEnd();
            });

            GigEdit.TextAreaExpander(tx);
            if (isList)
                DomElement.Trigger("TabLineCounter", tx);

            el.CSS(new Dictionary("color", "transparent")).Hide();
        }

        public static void EditText2(jQueryObject el)
        {
            GigData ggd = new GigData(null);
            ggd.type = "TextItem";
            ggd.listType = "ol";
            ggd.css = el.Plugin<Jewl>().GetStyles();

            bool escape = false;
            GigShowConfig cfg = GigShow.CssMap[ggd.type];
            //if (cfg == null || !cfg.doubleclick)
            //{
            //    return;
            //}
            bool isList = !String.IsNullOrEmpty(ggd.listType);
            //ThemeYoshi.SupressCurateEvents = true;
            jQueryObject ctt = el.Children().First().Find(cfg.inner).First();
            //Editor.Muffel();
            el.Find(".Cover").Hide();
            Dictionary css = ggd.css;
            Dictionary css2 = (Dictionary)jQuery.Extend(new Dictionary(), css);
            css2.Remove("margin");
            css2.Remove("padding");
            css2.Remove("border-style");
            css2.Remove("border-width");
            css2.Remove("padding-top");
            css2.Remove("padding-left");
            css2.Remove("padding-right");
            css2.Remove("padding-bottom");
            css2["overflow"] = "hidden";
            if (cfg.css) // If css is being applied to inner, as in form elements
            {
                int pv = Css.PaddingTop(css, Gig.DeefCss["padding-top"]);
                int ph = Css.PaddingLeft(css, Gig.DeefCss["padding-left"]);
                css2["color"] = ctt.GetCSS("color");
                css2["background-color"] = Css.RealBgColor(ctt);
                jQueryPosition p = ctt.GetOffset();
                jQuery.Extend(css2, new Dictionary("top", p.Top, "left", p.Left, "width", ctt.GetInnerWidth() - ph - ph, "height", ctt.GetInnerHeight() - pv - pv));
                jQuery.Extend(css2, new Dictionary("padding-left", ph, "padding-right", ph, "padding-top", pv, "padding-bottom", 0));
            }
            else
            {
                css2.Remove("border-radius");
                css2.Remove("-moz-border-radius");
                css2.Remove("-webkit-border-radius");
                css2["color"] = el.GetCSS("color");
                css2["background-color"] = Css.RealBgColor(el);
                jQueryPosition p = ctt.GetOffset();
                jQuery.Extend(css2, new Dictionary("top", p.Top - 1, "left", p.Left - 2, "width", ctt.GetInnerWidth() + 4, "height", ctt.GetInnerHeight() + 2));
                jQuery.Extend(css2, new Dictionary("padding-left", 2, "padding-right", 2, "padding-top", 1, "padding-bottom", 1));
            }
            if (cfg.inner == "button")
                css2["text-align"] = "center";
            string wrap = isList ? "off" : "soft";
            jQueryObject tx = jQuery.FromHtml("<textarea class='GigEditText AboveHider' wrap='" + wrap + "' style='position:absolute;padding:0;margin:0;border: 0px none transparent'/>");

            // Creep prevention requires change of 10px to auto-resize box after edit box size change.
            int sw = el.GetInnerWidth();
            int sh = el.GetInnerHeight();
            string value = ctt.Plugin<Jewl>().GetContent();

            Cluster.Glass(delegate { tx.Blur(); }).CSS(new Dictionary("background-color", "rgba(0,0,0,.25)"));

            //Inform.Debug("Edit value for [{0}] = {1}", cfg.inner, value);
            //Inform.Dump(css2, "css");

            Dictionary<string, KeyAction> editKeys = new Dictionary(
                "13:s",
                (KeyAction)delegate(jQueryEvent ek)
                {
                    DomElement.CancelEvent(ek);
                    Cluster.GlassOff();
                },
                "27:", /*esc*/
                (KeyAction)delegate(jQueryEvent ek)
                {
                    DomElement.CancelEvent(ek);
                    escape = true;
                    Cluster.GlassOff();
                },
                "9:", /*tab*/
                (KeyAction)delegate(jQueryEvent ek)
                {
                    DomElement.CancelEvent(ek);
                    Helpers.InsertText(tx, "\t");
                }
                );

            tx
                .AppendTo(Document.Body)
                .CSS(css2)
                .Plugin<Jewl>().FValue(GigParse.HtmlToList(value, ggd.listType))
                .Bind("blur.editev",
                      delegate
                      {
                          //ThemeYoshi.SupressCurateEvents = false;
                          DomElement.Trigger("TabLineCounter", false);
                          GigShow.MapCss(ggd, el, css);
                          ctt.Show();
                          int w = tx.GetInnerWidth();
                          int h = tx.GetInnerHeight();
                          if (w >= sw + 10)
                              el.CSS(new Dictionary("width", w));
                          if (h >= sh + 10)
                              el.CSS(new Dictionary("height", h));
                          // ReSharper disable AccessToModifiedClosure
                          if (!escape)
                          // ReSharper restore AccessToModifiedClosure
                          {
                              string txt = GigParse.ListToHtml(tx.Plugin<Jewl>().GetFEditString(), ggd.listType);
                              txt = String.IsNullOrEmpty(txt.Trim()) ? GigEdit.YourText : txt;
                              jQueryObject elx = el.Find(cfg.inner);
                              elx.Plugin<Jewl>().SetContent(txt);
                              ggd.html = GigEdit.ReplaceText(ggd.html, txt);
                          }

                          ctt.Show();
                          el.Find(".Cover").Show();
                          el.Find(".CoverInner").Show();
                          tx.Unbind(".editev").Remove();

                          //Inform.Debug("Edit outer html = {0}", MyGd.html);
                          //Editor.ReSlideAndSave(e);
                          Cluster.GlassOff(true);

                          //Editor.Listen();
                      })
                .Bind("keydown.editev",
                      delegate(jQueryEvent e2)
                      {
                          string k = Keys.DoKeys(e2, editKeys);
                          if (k == null)
                              return;

                          if (isList)
                          {
                              if (e2.Which == 13)
                              {
                                  //Window.SetTimeout(delegate { tx.Value(tx.GetValue().ReplaceRegex((RegularExpression) Script.Literal(@"/[\n\r\t]+/g"), "\n\t")); }, 1);
                                  Window.SetTimeout(delegate { tx.Value(tx.GetValue().ReplaceRegex((RegularExpression)Script.Literal(@"/[\n]([^\t])|\n$/g"), "\n\t$1")); }, 1);
                              }
                              else if (e2.Which == 8)
                              {
                                  Window.SetTimeout(delegate { tx.Value(tx.GetValue().ReplaceRegex((RegularExpression)Script.Literal(@"/[\n]([^\t])|\n$/g"), "$1")); }, 1);
                              }
                          }
                      })
                .Click().Focus().Plugin<Jewl>().CarotToEnd()
                ;
            if (tx.GetValue() == GigEdit.YourText)
                tx.Value("");

            //if (MyGd.autosize)
            GigEdit.TextAreaExpander(tx);

            ctt.Hide();

            if (isList)
                DomElement.Trigger("TabLineCounter", tx);

            //DomElement.CancelEvent(e);
        }

    }
}
